/*******************************************************************************
* Project: QSAR(Cute Software Architecture) 
*
* Copyright: Copyright(C) 2024 by YuetingBen, All Rights Reserved
*
* File name: DcmDspSvc2F.c
*
* Brief: ;
*
* Author: Yueting.Ben
*
* Module: Dcm
*
*******************************************************************************/

/** HEADER FILES **/
#include "DcmDspSvc2F.h"
#include "DcmDspDidType.h"
#include "DcmDspDidCfg.h"
#include "DcmDspDid.h"
#include "DcmDsp.h"


/** MACRO DEFINITION **/
#define DCM_PROGRESS_DID_CHECK ((Dcm_ProgressType)0x10u)
#define DCM_PROGRESS_ACCESS_CHECK ((Dcm_ProgressType)0x11u)
#define DCM_PROGRESS_CONTROL_RETURN_CONTROL_TO_ECU ((Dcm_ProgressType)0x12u)
#define DCM_PROGRESS_CONTROL_RESET_TO_DEFAULT ((Dcm_ProgressType)0x13u)
#define DCM_PROGRESS_CONTROL_FREEZE_CURRENT_STATE ((Dcm_ProgressType)0x14u)
#define DCM_PROGRESS_CONTROL_SHORT_TERM_ADJUSTMENT ((Dcm_ProgressType)0x15u)

#define DCM_REQ_INPUT_OUTPUT_CONTROL_PARAMETER_INDEX           2u
#define DCM_REQ_CONTROL_STATE_START_INDEX                       3u

#define DCM_RES_INPUT_OUTPUT_CONTROL_PARAMETER_INDEX   2u
#define DCM_RES_CONTROL_STATE_START_INDEX               3u


#define DCM_RETURN_CONTROL_TO_ECU  0x00
#define DCM_RESET_TO_DEFAULT   0x01
#define DCM_FREEZE_CURRENT_STATE   0x02
#define DCM_SHORT_TERM_ADJUSTMENT   0x03


/** TYPEDEF DEFINITION **/


/** LOCAL DATA DECLARATION **/


/** GLOBAL DATA DECLARATION **/


/** LOCAL FUNCTION DECLARATION **/


/** GLOBAL FUNCTION DECLARATION **/
Std_ReturnType DcmDsp_Svc2F_Processor(
    Dcm_ExtendedOpStatusType OpStatus,
    Dcm_MsgContextType* pMsgContext,
    Dcm_NegativeResponseCodeType* ErrorCode
);

/** LOCAL DATA **/


/** GLOBAL DATA **/


/** LOCAL FUNCTION **/


/** GLOBAL FUNCTION **/
Std_ReturnType DcmDsp_Svc2F_Processor(
    Dcm_ExtendedOpStatusType OpStatus,
    Dcm_MsgContextType* pMsgContext,
    Dcm_NegativeResponseCodeType* ErrorCode
)
{
    Std_ReturnType retVal = E_NOT_OK;
    DcmDspDidIdentifierType did;
    DcmDspDidInfoType* didInfoPtr;
    static DcmDspDidIndexType didIndex;
    DcmDspDidSignalIndexType signalIndex;
    Dcm_SesCtrlType sesCtrl;
    Dcm_SecLevelType secLevel;
    uint8 inputOutputControlParameter;
    uint8 controlStateInfo;
    
    switch(Dcm_GetProgress(pMsgContext))
    {
        case DCM_PROGRESS_INITIAL:
        {
            retVal = DCM_E_PENDING;
            Dcm_SetProgress(pMsgContext, DCM_PROGRESS_DID_CHECK);
            break;
        }
        case DCM_PROGRESS_DID_CHECK:
        {
            did = (DcmDspDidIdentifierType)(((DcmDspDidIdentifierType)pMsgContext->reqData[DCM_REQ_DATA_DID_HIGH_INDEX] << 8) + pMsgContext->reqData[DCM_REQ_DATA_DID_LOW_INDEX]);

            *ErrorCode = DCM_E_REQUESTOUTOFRANGE;
            for(didIndex = 0u; didIndex < DcmDspDidConf_DidIndex_Max; didIndex++)
            {
                didInfoPtr = (DcmDspDidInfoType*)(&DcmDspDidInfoCfg[didIndex]);
                if(did == didInfoPtr->did)
                {
                    Dcm_SetProgress(pMsgContext, DCM_PROGRESS_LENGTH_FORMAT_CHECK);
                    retVal = DCM_E_PENDING;
                    break;
                }
            }
            break;
        }
        case DCM_PROGRESS_LENGTH_FORMAT_CHECK:
        {
            retVal = DCM_E_PENDING;
            didInfoPtr = (DcmDspDidInfoType*)(&DcmDspDidInfoCfg[didIndex]);
            if(DCMDSPSVC2F_REQ_DATA_MINLENGTH <= pMsgContext->reqDataLen)
            {
                Dcm_SetProgress(pMsgContext, DCM_PROGRESS_ACCESS_CHECK);
            }
            else
            {
                *ErrorCode = DCM_E_INCORRECTMES_SAGELENGTHORINVALID_FORMAT;
                retVal = E_NOT_OK;
            }
            break;
        }
        case DCM_PROGRESS_ACCESS_CHECK:
        {
            didInfoPtr = (DcmDspDidInfoType*)(&DcmDspDidInfoCfg[didIndex]);
            retVal = DcmDsp_SessionCheck((DcmDspSessionType*)&didInfoPtr->controlAccess.didControlSessionLevel);
            if(E_OK == retVal)
            {
                retVal = DcmDsp_SecurityCheck((DcmDspSessionType*)&didInfoPtr->controlAccess.didControlSecurityLevel);
                if(E_OK == retVal)
                {
                    retVal = DCM_E_PENDING;
                    inputOutputControlParameter = pMsgContext->reqData[DCM_REQ_INPUT_OUTPUT_CONTROL_PARAMETER_INDEX];
                    if(DCM_RETURN_CONTROL_TO_ECU == inputOutputControlParameter)
                    {
                        Dcm_SetProgress(pMsgContext, DCM_PROGRESS_CONTROL_RETURN_CONTROL_TO_ECU);
                    }
                    else if(DCM_RESET_TO_DEFAULT == inputOutputControlParameter)
                    {
                        Dcm_SetProgress(pMsgContext, DCM_PROGRESS_CONTROL_RESET_TO_DEFAULT);
                    }
                    else if(DCM_FREEZE_CURRENT_STATE == inputOutputControlParameter)
                    {
                        Dcm_SetProgress(pMsgContext, DCM_PROGRESS_CONTROL_FREEZE_CURRENT_STATE);
                    }
                    else if(DCM_SHORT_TERM_ADJUSTMENT == inputOutputControlParameter)
                    {
                        Dcm_SetProgress(pMsgContext, DCM_PROGRESS_CONTROL_SHORT_TERM_ADJUSTMENT);
                    }
                    else
                    {
                        *ErrorCode = DCM_E_REQUESTOUTOFRANGE;
                    }
                }
                else
                {
                    *ErrorCode = DCM_E_SECURITYACCESSDENIED;
                }
            }
            else
            {
                *ErrorCode = DCM_E_REQUESTOUTOFRANGE;
            }  
            break;
        }

        case DCM_PROGRESS_CONTROL_RETURN_CONTROL_TO_ECU:
        {
            didInfoPtr = (DcmDspDidInfoType*)(&DcmDspDidInfoCfg[didIndex]);
            for(signalIndex = 0u; signalIndex < (didInfoPtr->signalNum); signalIndex++)
            {
                if(NULL_PTR != didInfoPtr->signalPtr[signalIndex].didDataPtr->dataReturnControlToEcuFnc)
                {
                    retVal = didInfoPtr->signalPtr[signalIndex].didDataPtr->dataReturnControlToEcuFnc((uint8*)(&pMsgContext->reqData[DCM_REQ_CONTROL_STATE_START_INDEX]),
                                                                                                      ErrorCode);
                    retVal |= didInfoPtr->signalPtr[signalIndex].didDataPtr->dataReadFnc(&pMsgContext->resData[DCM_RES_CONTROL_STATE_START_INDEX + didInfoPtr->signalPtr[signalIndex].didByteOffset]);
                    pMsgContext->resDataLen = 3u + didInfoPtr->didSize;
                }
            }
            break;

        }
        case DCM_PROGRESS_CONTROL_RESET_TO_DEFAULT:
        {
            didInfoPtr = (DcmDspDidInfoType*)(&DcmDspDidInfoCfg[didIndex]);
            for(signalIndex = 0u; signalIndex < (didInfoPtr->signalNum); signalIndex++)
            {
                if(NULL_PTR != didInfoPtr->signalPtr[signalIndex].didDataPtr->dataResetToDefaultFnc)
                {
                    retVal = didInfoPtr->signalPtr[signalIndex].didDataPtr->dataResetToDefaultFnc((uint8*)(&pMsgContext->reqData[DCM_REQ_CONTROL_STATE_START_INDEX]),
                                                                                                      ErrorCode);
                    retVal |= didInfoPtr->signalPtr[signalIndex].didDataPtr->dataReadFnc(&pMsgContext->resData[DCM_RES_CONTROL_STATE_START_INDEX + didInfoPtr->signalPtr[signalIndex].didByteOffset]);
                    pMsgContext->resDataLen = 3u + didInfoPtr->didSize;
                }
            }
            break;

        }
        case DCM_PROGRESS_CONTROL_FREEZE_CURRENT_STATE:
        {
            didInfoPtr = (DcmDspDidInfoType*)(&DcmDspDidInfoCfg[didIndex]);
            for(signalIndex = 0u; signalIndex < (didInfoPtr->signalNum); signalIndex++)
            {
                if(NULL_PTR != didInfoPtr->signalPtr[signalIndex].didDataPtr->DcmDspDataFreezeCurrentStateFnc)
                {
                    retVal = didInfoPtr->signalPtr[signalIndex].didDataPtr->DcmDspDataFreezeCurrentStateFnc((uint8*)(&pMsgContext->reqData[DCM_REQ_CONTROL_STATE_START_INDEX]),
                                                                                                            ErrorCode);
                    retVal |= didInfoPtr->signalPtr[signalIndex].didDataPtr->dataReadFnc(&pMsgContext->resData[DCM_RES_CONTROL_STATE_START_INDEX + didInfoPtr->signalPtr[signalIndex].didByteOffset]);
                    pMsgContext->resDataLen = 3u + didInfoPtr->didSize;
                }
            }
            break;

        }
        case DCM_PROGRESS_CONTROL_SHORT_TERM_ADJUSTMENT:
        {
            didInfoPtr = (DcmDspDidInfoType*)(&DcmDspDidInfoCfg[didIndex]);
            for(signalIndex = 0u; signalIndex < (didInfoPtr->signalNum); signalIndex++)
            {
                if(NULL_PTR != didInfoPtr->signalPtr[signalIndex].didDataPtr->dataShortTermAdjustmentFnc)
                {
                    retVal = didInfoPtr->signalPtr[signalIndex].didDataPtr->dataShortTermAdjustmentFnc((uint8*)&controlStateInfo,
                                                                                                       (uint8*)(&pMsgContext->reqData[DCM_REQ_CONTROL_STATE_START_INDEX + didInfoPtr->didSize]),
                                                                                                       ErrorCode);
                    retVal |= didInfoPtr->signalPtr[signalIndex].didDataPtr->dataReadFnc(&pMsgContext->resData[DCM_RES_CONTROL_STATE_START_INDEX + didInfoPtr->signalPtr[signalIndex].didByteOffset]);
                    pMsgContext->resDataLen = 3u + didInfoPtr->didSize;
                }
            }
            break;

        }
        default:
        {
            *ErrorCode = DCM_E_REQUESTOUTOFRANGE;
            break;
        }
    }

    return(retVal);
}




